/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
 
This file is part of Quake III Arena source code.
 
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
 
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
===========================================================================
*/
#include "../game/q_shared.h"
#include "qcommon.h"
#include <stddef.h>

static huffman_t		msgHuff;

static qboolean			msgInit = qfalse;

int pcount[256];

/*
==============================================================================
 
			MESSAGE IO FUNCTIONS
 
Handles byte ordering and avoids alignment errors
==============================================================================
*/

int oldsize = 0;

void MSG_initHuffman(void);

void MSG_Init( msg_t *buf, byte *data, int length )
{
    if (!msgInit)
    {
        MSG_initHuffman();
    }
    Com_Memset (buf, 0, sizeof(*buf));
    buf->data = data;
    buf->maxsize = length;
}

void MSG_InitOOB( msg_t *buf, byte *data, int length )
{
    if (!msgInit)
    {
        MSG_initHuffman();
    }
    Com_Memset (buf, 0, sizeof(*buf));
    buf->data = data;
    buf->maxsize = length;
    buf->oob = qtrue;
}

void MSG_Clear( msg_t *buf )
{
    buf->cursize = 0;
    buf->overflowed = qfalse;
    buf->bit = 0;					//<- in bits
}


void MSG_Bitstream( msg_t *buf )
{
    buf->oob = qfalse;
}

void MSG_BeginReading( msg_t *msg )
{
    msg->readcount = 0;
    msg->bit = 0;
    msg->oob = qfalse;
}

void MSG_BeginReadingOOB( msg_t *msg )
{
    msg->readcount = 0;
    msg->bit = 0;
    msg->oob = qtrue;
}

void MSG_Copy(msg_t *buf, byte *data, int length, msg_t *src)
{
    if (length<src->cursize)
    {
        Com_Error( ERR_DROP, "MSG_Copy: can't copy into a smaller msg_t buffer");
    }
    Com_Memcpy(buf, src, sizeof(msg_t));
    buf->data = data;
    Com_Memcpy(buf->data, src->data, src->cursize);
}

/*
=============================================================================
 
bit functions
  
=============================================================================
*/

int	overflows;

// negative bit values include signs
void MSG_WriteBits( msg_t *msg, int value, int bits )
{
    int	i;
    //	FILE*	fp;

    oldsize += bits;

    // this isn't an exact overflow check, but close enough
    if ( msg->maxsize - msg->cursize < 4 )
    {
        msg->overflowed = qtrue;
        return;
    }

    if ( bits == 0 || bits < -31 || bits > 32 )
    {
        Com_Error( ERR_DROP, "MSG_WriteBits: bad bits %i", bits );
    }

    // check for overflows
    if ( bits != 32 )
    {
        if ( bits > 0 )
        {
            if ( value > ( ( 1 << bits ) - 1 ) || value < 0 )
            {
                overflows++;
            }
        }
        else
        {
            int	r;

            r = 1 << (bits-1);

            if ( value >  r - 1 || value < -r )
            {
                overflows++;
            }
        }
    }
    if ( bits < 0 )
    {
        bits = -bits;
    }
    if (msg->oob)
    {
        if (bits==8)
        {
            msg->data[msg->cursize] = value;
            msg->cursize += 1;
            msg->bit += 8;
        }
        else if (bits==16)
        {
            unsigned short *sp = (unsigned short *)&msg->data[msg->cursize];
            *sp = LittleShort(value);
            msg->cursize += 2;
            msg->bit += 16;
        }
        else if (bits==32)
        {
            unsigned int *ip = (unsigned int *)&msg->data[msg->cursize];
            *ip = LittleLong(value);
            msg->cursize += 4;
            msg->bit += 8;
        }
        else
        {
            Com_Error(ERR_DROP, "can't read %d bits\n", bits);
        }
    }
    else
    {
        //		fp = fopen("c:\\netchan.bin", "a");
        value &= (0xffffffff>>(32-bits));
        if (bits&7)
        {
            int nbits;
            nbits = bits&7;
            for(i=0;i<nbits;i++)
            {
                Huff_putBit((value&1), msg->data, &msg->bit);
                value = (value>>1);
            }
            bits = bits - nbits;
        }
        if (bits)
        {
            for(i=0;i<bits;i+=8)
            {
                //				fwrite(bp, 1, 1, fp);
                Huff_offsetTransmit (&msgHuff.compressor, (value&0xff), msg->data, &msg->bit);
                value = (value>>8);
            }
        }
        msg->cursize = (msg->bit>>3)+1;
        //		fclose(fp);
    }
}

int MSG_ReadBits( msg_t *msg, int bits )
{
    int			value;
    int			get;
    qboolean	sgn;
    int			i, nbits;
    //	FILE*	fp;

    value = 0;

    if ( bits < 0 )
    {
        bits = -bits;
        sgn = qtrue;
    }
    else
    {
        sgn = qfalse;
    }

    if (msg->oob)
    {
        if (bits==8)
        {
            value = msg->data[msg->readcount];
            msg->readcount += 1;
            msg->bit += 8;
        }
        else if (bits==16)
        {
            unsigned short *sp = (unsigned short *)&msg->data[msg->readcount];
            value = LittleShort(*sp);
            msg->readcount += 2;
            msg->bit += 16;
        }
        else if (bits==32)
        {
            unsigned int *ip = (unsigned int *)&msg->data[msg->readcount];
            value = LittleLong(*ip);
            msg->readcount += 4;
            msg->bit += 32;
        }
        else
        {
            Com_Error(ERR_DROP, "can't read %d bits\n", bits);
        }
    }
    else
    {
        nbits = 0;
        if (bits&7)
        {
            nbits = bits&7;
            for(i=0;i<nbits;i++)
            {
                value |= (Huff_getBit(msg->data, &msg->bit)<<i);
            }
            bits = bits - nbits;
        }
        if (bits)
        {
            //			fp = fopen("c:\\netchan.bin", "a");
            for(i=0;i<bits;i+=8)
            {
                Huff_offsetReceive (msgHuff.decompressor.tree, &get, msg->data, &msg->bit);
                //				fwrite(&get, 1, 1, fp);
                value |= (get<<(i+nbits));
            }
            //			fclose(fp);
        }
        msg->readcount = (msg->bit>>3)+1;
    }
    if ( sgn )
    {
        if ( value & ( 1 << ( bits - 1 ) ) )
        {
            value |= -1 ^ ( ( 1 << bits ) - 1 );
        }
    }

    return value;
}



//================================================================================

//
// writing functions
//

void MSG_WriteChar( msg_t *sb, int c )
{
#ifdef PARANOID
    if (c < -128 || c > 127)
        Com_Error (ERR_FATAL, "MSG_WriteChar: range error");
#endif

    MSG_WriteBits( sb, c, 8 );
}

void MSG_WriteByte( msg_t *sb, int c )
{
#ifdef PARANOID
    if (c < 0 || c > 255)
        Com_Error (ERR_FATAL, "MSG_WriteByte: range error");
#endif

    MSG_WriteBits( sb, c, 8 );
}

void MSG_WriteData( msg_t *buf, const void *data, int length )
{
    int i;
    for(i=0;i<length;i++)
    {
        MSG_WriteByte(buf, ((byte *)data)[i]);
    }
}

void MSG_WriteShort( msg_t *sb, int c )
{
#ifdef PARANOID
    if (c < ((short)0x8000) || c > (short)0x7fff)
        Com_Error (ERR_FATAL, "MSG_WriteShort: range error");
#endif

    MSG_WriteBits( sb, c, 16 );
}

void MSG_WriteLong( msg_t *sb, int c )
{
    MSG_WriteBits( sb, c, 32 );
}

void MSG_WriteFloat( msg_t *sb, float f )
{
    union {
        float	f;
        int	l;
    } dat;

    dat.f = f;
    MSG_WriteBits( sb, dat.l, 32 );
}

void MSG_WriteString( msg_t *sb, const char *s )
{
    if ( !s )
    {
        MSG_WriteData (sb, "", 1);
    }
    else
    {
        int		l,i;
        char	string[MAX_STRING_CHARS];

        l = strlen( s );
        if ( l >= MAX_STRING_CHARS )
        {
            Com_Printf( "MSG_WriteString: MAX_STRING_CHARS" );
            MSG_WriteData (sb, "", 1);
            return;
        }
        Q_strncpyz( string, s, sizeof( string ) );

        // get rid of 0xff chars, because old clients don't like them
        for ( i = 0 ; i < l ; i++ )
        {
            if ( ((byte *)string)[i] > 127 )
            {
                string[i] = '.';
            }
        }

        MSG_WriteData (sb, string, l+1);
    }
}

void MSG_WriteBigString( msg_t *sb, const char *s )
{
    if ( !s )
    {
        MSG_WriteData (sb, "", 1);
    }
    else
    {
        int		l,i;
        char	string[BIG_INFO_STRING];

        l = strlen( s );
        if ( l >= BIG_INFO_STRING )
        {
            Com_Printf( "MSG_WriteString: BIG_INFO_STRING" );
            MSG_WriteData (sb, "", 1);
            return;
        }
        Q_strncpyz( string, s, sizeof( string ) );

        // get rid of 0xff chars, because old clients don't like them
        for ( i = 0 ; i < l ; i++ )
        {
            if ( ((byte *)string)[i] > 127 )
            {
                string[i] = '.';
            }
        }

        MSG_WriteData (sb, string, l+1);
    }
}

void MSG_WriteAngle( msg_t *sb, float f )
{
    MSG_WriteByte (sb, (int)(f*256/360) & 255);
}

void MSG_WriteAngle16( msg_t *sb, float f )
{
    MSG_WriteShort (sb, ANGLE2SHORT(f));
}


//============================================================

//
// reading functions
//

// returns -1 if no more characters are available
int MSG_ReadChar (msg_t *msg )
{
    int	c;

    c = (signed char)MSG_ReadBits( msg, 8 );
    if ( msg->readcount > msg->cursize )
    {
        c = -1;
    }

    return c;
}

int MSG_ReadByte( msg_t *msg )
{
    int	c;

    c = (unsigned char)MSG_ReadBits( msg, 8 );
    if ( msg->readcount > msg->cursize )
    {
        c = -1;
    }
    return c;
}

int MSG_ReadShort( msg_t *msg )
{
    int	c;

    c = (short)MSG_ReadBits( msg, 16 );
    if ( msg->readcount > msg->cursize )
    {
        c = -1;
    }

    return c;
}

int MSG_ReadLong( msg_t *msg )
{
    int	c;

    c = MSG_ReadBits( msg, 32 );
    if ( msg->readcount > msg->cursize )
    {
        c = -1;
    }

    return c;
}

float MSG_ReadFloat( msg_t *msg )
{
    union {
        byte	b[4];
        float	f;
        int	l;
    } dat;

    dat.l = MSG_ReadBits( msg, 32 );
    if ( msg->readcount > msg->cursize )
    {
        dat.f = -1;
    }

    return dat.f;
}

char *MSG_ReadString( msg_t *msg )
{
    static char     string[MAX_STRING_CHARS];
    unsigned int    l;
    int             c;

    l = 0;
    do
    {
        c = MSG_ReadByte(msg);		// use ReadByte so -1 is out of bounds
        if ( c == -1 || c == 0 )
        {
            break;
        }
        // translate all fmt spec to avoid crash bugs
        if ( c == '%' )
        {
            c = '.';
        }
        // don't allow higher ascii values
        if ( c > 127 )
        {
            c = '.';
        }

        string[l] = c;
        l++;
    }
    while (l < sizeof(string)-1);

    string[l] = 0;

    return string;
}

char *MSG_ReadBigString( msg_t *msg )
{
    static char     string[BIG_INFO_STRING];
    unsigned int    l;
    int             c;

    l = 0;
    do
    {
        c = MSG_ReadByte(msg);		// use ReadByte so -1 is out of bounds
        if ( c == -1 || c == 0 )
        {
            break;
        }
        // translate all fmt spec to avoid crash bugs
        if ( c == '%' )
        {
            c = '.';
        }

        string[l] = c;
        l++;
    }
    while (l < sizeof(string)-1);

    string[l] = 0;

    return string;
}

char *MSG_ReadStringLine( msg_t *msg )
{
    static char     string[MAX_STRING_CHARS];
    unsigned int    l;
    int             c;

    l = 0;
    do
    {
        c = MSG_ReadByte(msg);		// use ReadByte so -1 is out of bounds
        if (c == -1 || c == 0 || c == '\n')
        {
            break;
        }
        // translate all fmt spec to avoid crash bugs
        if ( c == '%' )
        {
            c = '.';
        }
        string[l] = c;
        l++;
    }
    while (l < sizeof(string)-1);

    string[l] = 0;

    return string;
}

float MSG_ReadAngle16( msg_t *msg )
{
    return SHORT2ANGLE(MSG_ReadShort(msg));
}

void MSG_ReadData( msg_t *msg, void *data, int len )
{
    int		i;

    for (i=0 ; i<len ; i++)
    {
        ((byte *)data)[i] = MSG_ReadByte (msg);
    }
}


/*
=============================================================================
 
delta functions
  
=============================================================================
*/

extern cvar_t *cl_shownet;

#define	LOG(x) if( cl_shownet->integer == 4 ) { Com_Printf("%s ", x ); };

void MSG_WriteDelta( msg_t *msg, int oldV, int newV, int bits )
{
    if ( oldV == newV )
    {
        MSG_WriteBits( msg, 0, 1 );
        return;
    }
    MSG_WriteBits( msg, 1, 1 );
    MSG_WriteBits( msg, newV, bits );
}

int	MSG_ReadDelta( msg_t *msg, int oldV, int bits )
{
    if ( MSG_ReadBits( msg, 1 ) )
    {
        return MSG_ReadBits( msg, bits );
    }
    return oldV;
}

void MSG_WriteDeltaFloat( msg_t *msg, float oldV, float newV )
{
    if ( oldV == newV )
    {
        MSG_WriteBits( msg, 0, 1 );
        return;
    }
    MSG_WriteBits( msg, 1, 1 );
    MSG_WriteBits( msg, *(int *)&newV, 32 );
}

float MSG_ReadDeltaFloat( msg_t *msg, float oldV )
{
    if ( MSG_ReadBits( msg, 1 ) )
    {
        float	newV;

        *(int *)&newV = MSG_ReadBits( msg, 32 );
        return newV;
    }
    return oldV;
}

/*
=============================================================================
 
delta functions with keys
  
=============================================================================
*/

int kbitmask[32] = {
                       0x00000001, 0x00000003, 0x00000007, 0x0000000F,
                       0x0000001F,	0x0000003F,	0x0000007F,	0x000000FF,
                       0x000001FF,	0x000003FF,	0x000007FF,	0x00000FFF,
                       0x00001FFF,	0x00003FFF,	0x00007FFF,	0x0000FFFF,
                       0x0001FFFF,	0x0003FFFF,	0x0007FFFF,	0x000FFFFF,
                       0x001FFFFf,	0x003FFFFF,	0x007FFFFF,	0x00FFFFFF,
                       0x01FFFFFF,	0x03FFFFFF,	0x07FFFFFF,	0x0FFFFFFF,
                       0x1FFFFFFF,	0x3FFFFFFF,	0x7FFFFFFF,	0xFFFFFFFF,
                   };

void MSG_WriteDeltaKey( msg_t *msg, int key, int oldV, int newV, int bits )
{
    if ( oldV == newV )
    {
        MSG_WriteBits( msg, 0, 1 );
        return;
    }
    MSG_WriteBits( msg, 1, 1 );
    MSG_WriteBits( msg, newV ^ key, bits );
}

int	MSG_ReadDeltaKey( msg_t *msg, int key, int oldV, int bits )
{
    if ( MSG_ReadBits( msg, 1 ) )
    {
        return MSG_ReadBits( msg, bits ) ^ (key & kbitmask[bits]);
    }
    return oldV;
}

void MSG_WriteDeltaKeyFloat( msg_t *msg, int key, float oldV, float newV )
{
    if ( oldV == newV )
    {
        MSG_WriteBits( msg, 0, 1 );
        return;
    }
    MSG_WriteBits( msg, 1, 1 );
    MSG_WriteBits( msg, (*(int *)&newV) ^ key, 32 );
}

float MSG_ReadDeltaKeyFloat( msg_t *msg, int key, float oldV )
{
    if ( MSG_ReadBits( msg, 1 ) )
    {
        float	newV;

        *(int *)&newV = MSG_ReadBits( msg, 32 ) ^ key;
        return newV;
    }
    return oldV;
}


/*
============================================================================
 
usercmd_t communication
 
============================================================================
*/

// ms is allways sent, the others are optional
#define	CM_ANGLE1 	(1<<0)
#define	CM_ANGLE2 	(1<<1)
#define	CM_ANGLE3 	(1<<2)
#define	CM_FORWARD	(1<<3)
#define	CM_SIDE		(1<<4)
#define	CM_UP		(1<<5)
#define	CM_BUTTONS	(1<<6)
#define CM_WEAPON	(1<<7)

/*
=====================
MSG_WriteDeltaUsercmd
=====================
*/
void MSG_WriteDeltaUsercmd( msg_t *msg, usercmd_t *from, usercmd_t *to )
{
    if ( to->serverTime - from->serverTime < 256 )
    {
        MSG_WriteBits( msg, 1, 1 );
        MSG_WriteBits( msg, to->serverTime - from->serverTime, 8 );
    }
    else
    {
        MSG_WriteBits( msg, 0, 1 );
        MSG_WriteBits( msg, to->serverTime, 32 );
    }
    MSG_WriteDelta( msg, from->angles[0], to->angles[0], 16 );
    MSG_WriteDelta( msg, from->angles[1], to->angles[1], 16 );
    MSG_WriteDelta( msg, from->angles[2], to->angles[2], 16 );
    MSG_WriteDelta( msg, from->forwardmove, to->forwardmove, 8 );
    MSG_WriteDelta( msg, from->rightmove, to->rightmove, 8 );
    MSG_WriteDelta( msg, from->upmove, to->upmove, 8 );
    MSG_WriteDelta( msg, from->buttons, to->buttons, 16 );
    MSG_WriteDelta( msg, from->weapon, to->weapon, 8 );
}


/*
=====================
MSG_ReadDeltaUsercmd
=====================
*/
void MSG_ReadDeltaUsercmd( msg_t *msg, usercmd_t *from, usercmd_t *to )
{
    if ( MSG_ReadBits( msg, 1 ) )
    {
        to->serverTime = from->serverTime + MSG_ReadBits( msg, 8 );
    }
    else
    {
        to->serverTime = MSG_ReadBits( msg, 32 );
    }
    to->angles[0] = MSG_ReadDelta( msg, from->angles[0], 16);
    to->angles[1] = MSG_ReadDelta( msg, from->angles[1], 16);
    to->angles[2] = MSG_ReadDelta( msg, from->angles[2], 16);
    to->forwardmove = MSG_ReadDelta( msg, from->forwardmove, 8);
    to->rightmove = MSG_ReadDelta( msg, from->rightmove, 8);
    to->upmove = MSG_ReadDelta( msg, from->upmove, 8);
    to->buttons = MSG_ReadDelta( msg, from->buttons, 16);
    to->weapon = MSG_ReadDelta( msg, from->weapon, 8);
}

/*
=====================
MSG_WriteDeltaUsercmd
=====================
*/
void MSG_WriteDeltaUsercmdKey( msg_t *msg, int key, usercmd_t *from, usercmd_t *to )
{
    if ( to->serverTime - from->serverTime < 256 )
    {
        MSG_WriteBits( msg, 1, 1 );
        MSG_WriteBits( msg, to->serverTime - from->serverTime, 8 );
    }
    else
    {
        MSG_WriteBits( msg, 0, 1 );
        MSG_WriteBits( msg, to->serverTime, 32 );
    }
    if (from->angles[0] == to->angles[0] &&
            from->angles[1] == to->angles[1] &&
            from->angles[2] == to->angles[2] &&
            from->forwardmove == to->forwardmove &&
            from->rightmove == to->rightmove &&
            from->upmove == to->upmove &&
            from->buttons == to->buttons &&
            from->weapon == to->weapon)
    {
        MSG_WriteBits( msg, 0, 1 );				// no change
        oldsize += 7;
        return;
    }
    key ^= to->serverTime;
    MSG_WriteBits( msg, 1, 1 );
    MSG_WriteDeltaKey( msg, key, from->angles[0], to->angles[0], 16 );
    MSG_WriteDeltaKey( msg, key, from->angles[1], to->angles[1], 16 );
    MSG_WriteDeltaKey( msg, key, from->angles[2], to->angles[2], 16 );
    MSG_WriteDeltaKey( msg, key, from->forwardmove, to->forwardmove, 8 );
    MSG_WriteDeltaKey( msg, key, from->rightmove, to->rightmove, 8 );
    MSG_WriteDeltaKey( msg, key, from->upmove, to->upmove, 8 );
    MSG_WriteDeltaKey( msg, key, from->buttons, to->buttons, 16 );
    MSG_WriteDeltaKey( msg, key, from->weapon, to->weapon, 8 );
}


/*
=====================
MSG_ReadDeltaUsercmd
=====================
*/
void MSG_ReadDeltaUsercmdKey( msg_t *msg, int key, usercmd_t *from, usercmd_t *to )
{
    if ( MSG_ReadBits( msg, 1 ) )
    {
        to->serverTime = from->serverTime + MSG_ReadBits( msg, 8 );
    }
    else
    {
        to->serverTime = MSG_ReadBits( msg, 32 );
    }
    if ( MSG_ReadBits( msg, 1 ) )
    {
        key ^= to->serverTime;
        to->angles[0] = MSG_ReadDeltaKey( msg, key, from->angles[0], 16);
        to->angles[1] = MSG_ReadDeltaKey( msg, key, from->angles[1], 16);
        to->angles[2] = MSG_ReadDeltaKey( msg, key, from->angles[2], 16);
        to->forwardmove = MSG_ReadDeltaKey( msg, key, from->forwardmove, 8);
        to->rightmove = MSG_ReadDeltaKey( msg, key, from->rightmove, 8);
        to->upmove = MSG_ReadDeltaKey( msg, key, from->upmove, 8);
        to->buttons = MSG_ReadDeltaKey( msg, key, from->buttons, 16);
        to->weapon = MSG_ReadDeltaKey( msg, key, from->weapon, 8);
    }
    else
    {
        to->angles[0] = from->angles[0];
        to->angles[1] = from->angles[1];
        to->angles[2] = from->angles[2];
        to->forwardmove = from->forwardmove;
        to->rightmove = from->rightmove;
        to->upmove = from->upmove;
        to->buttons = from->buttons;
        to->weapon = from->weapon;
    }
}

/*
=============================================================================
 
entityState_t communication
  
=============================================================================
*/

/*
=================
MSG_ReportChangeVectors_f
 
Prints out a table from the current statistics for copying to code
=================
*/
void MSG_ReportChangeVectors_f( void )
{
    int i;
    for(i=0;i<256;i++)
    {
        if (pcount[i])
        {
            Com_Printf("%d used %d\n", i, pcount[i]);
        }
    }
}

typedef struct
{
    char	*name;
    int		offset;
    int		bits;		// 0 = float
}
netField_t;

// using the stringizing operator to save typing...
#define	NETF(x) #x, offsetof(entityState_t, x)

netField_t	entityStateFields[] =
    {
        { NETF(pos.trTime), 32 },
        { NETF(pos.trBase[0]), 0 },
        { NETF(pos.trBase[1]), 0 },
        { NETF(pos.trDelta[0]), 0 },
        { NETF(pos.trDelta[1]), 0 },
        { NETF(pos.trBase[2]), 0 },
        { NETF(apos.trBase[1]), 0 },
        { NETF(pos.trDelta[2]), 0 },
        { NETF(apos.trBase[0]), 0 },
        { NETF(event), 10 },
        { NETF(angles2[1]), 0 },
        { NETF(eType), 8 },
        { NETF(torsoAnim), 8 },
        { NETF(eventParm), 8 },
        { NETF(legsAnim), 8 },
        { NETF(groundEntityNum), GENTITYNUM_BITS },
        { NETF(pos.trType), 8 },
        { NETF(eFlags), 19 },
        { NETF(otherEntityNum), GENTITYNUM_BITS },
        { NETF(weapon), 8 },
        { NETF(clientNum), 8 },
        { NETF(angles[1]), 0 },
        { NETF(pos.trDuration), 32 },
        { NETF(apos.trType), 8 },
        { NETF(origin[0]), 0 },
        { NETF(origin[1]), 0 },
        { NETF(origin[2]), 0 },
        { NETF(solid), 24 },
        { NETF(powerups), 16 },
        { NETF(modelindex), 8 },
        { NETF(otherEntityNum2), GENTITYNUM_BITS },
        { NETF(loopSound), 8 },
        { NETF(generic1), 8 },
        { NETF(origin2[2]), 0 },
        { NETF(origin2[0]), 0 },
        { NETF(origin2[1]), 0 },
        { NETF(modelindex2), 8 },
        { NETF(angles[0]), 0 },
        { NETF(time), 32 },
        { NETF(apos.trTime), 32 },
        { NETF(apos.trDuration), 32 },
        { NETF(apos.trBase[2]), 0 },
        { NETF(apos.trDelta[0]), 0 },
        { NETF(apos.trDelta[1]), 0 },
        { NETF(apos.trDelta[2]), 0 },
        { NETF(time2), 32 },
        { NETF(angles[2]), 0 },
        { NETF(angles2[0]), 0 },
        { NETF(angles2[2]), 0 },
        { NETF(constantLight), 32 },
        { NETF(frame), 16 }
    };


// if (int)f == f and (int)f + ( 1<<(FLOAT_INT_BITS-1) ) < ( 1 << FLOAT_INT_BITS )
// the float will be sent with FLOAT_INT_BITS, otherwise all 32 bits will be sent
#define	FLOAT_INT_BITS	13
#define	FLOAT_INT_BIAS	(1<<(FLOAT_INT_BITS-1))

/*
==================
MSG_WriteDeltaEntity
 
Writes part of a packetentities message, including the entity number.
Can delta from either a baseline or a previous packet_entity
If to is NULL, a remove entity update will be sent
If force is not set, then nothing at all will be generated if the entity is
identical, under the assumption that the in-order delta code will catch it.
==================
*/
void MSG_WriteDeltaEntity( msg_t *msg, struct entityState_s *from, struct entityState_s *to,
                           qboolean force )
{
    int			i, lc;
    int			numFields;
    netField_t	*field;
    int			trunc;
    float		fullFloat;
    int			*fromF, *toF;

    numFields = sizeof(entityStateFields)/sizeof(entityStateFields[0]);

    // all fields should be 32 bits to avoid any compiler packing issues
    // the "number" field is not part of the field list
    // if this assert fails, someone added a field to the entityState_t
    // struct without updating the message fields
    assert( numFields + 1 == sizeof( *from )/4 );

    // a NULL to is a delta remove message
    if ( to == NULL )
    {
        if ( from == NULL )
        {
            return;
        }
        MSG_WriteBits( msg, from->number, GENTITYNUM_BITS );
        MSG_WriteBits( msg, 1, 1 );
        return;
    }

    if ( to->number < 0 || to->number >= MAX_GENTITIES )
    {
        Com_Error (ERR_FATAL, "MSG_WriteDeltaEntity: Bad entity number: %i", to->number );
    }

    lc = 0;
    // build the change vector as bytes so it is endien independent
    for ( i = 0, field = entityStateFields ; i < numFields ; i++, field++ )
    {
        fromF = (int *)( (byte *)from + field->offset );
        toF = (int *)( (byte *)to + field->offset );
        if ( *fromF != *toF )
        {
            lc = i+1;
        }
    }

    if ( lc == 0 )
    {
        // nothing at all changed
        if ( !force )
        {
            return;		// nothing at all
        }
        // write two bits for no change
        MSG_WriteBits( msg, to->number, GENTITYNUM_BITS );
        MSG_WriteBits( msg, 0, 1 );		// not removed
        MSG_WriteBits( msg, 0, 1 );		// no delta
        return;
    }

    MSG_WriteBits( msg, to->number, GENTITYNUM_BITS );
    MSG_WriteBits( msg, 0, 1 );			// not removed
    MSG_WriteBits( msg, 1, 1 );			// we have a delta

    MSG_WriteByte( msg, lc );	// # of changes

    oldsize += numFields;

    for ( i = 0, field = entityStateFields ; i < lc ; i++, field++ )
    {
        fromF = (int *)( (byte *)from + field->offset );
        toF = (int *)( (byte *)to + field->offset );

        if ( *fromF == *toF )
        {
            MSG_WriteBits( msg, 0, 1 );	// no change
            continue;
        }

        MSG_WriteBits( msg, 1, 1 );	// changed

        if ( field->bits == 0 )
        {
            // float
            fullFloat = *(float *)toF;
            trunc = (int)fullFloat;

            if (fullFloat == 0.0f)
            {
                MSG_WriteBits( msg, 0, 1 );
                oldsize += FLOAT_INT_BITS;
            }
            else
            {
                MSG_WriteBits( msg, 1, 1 );
                if ( trunc == fullFloat && trunc + FLOAT_INT_BIAS >= 0 &&
                        trunc + FLOAT_INT_BIAS < ( 1 << FLOAT_INT_BITS ) )
                {
                    // send as small integer
                    MSG_WriteBits( msg, 0, 1 );
                    MSG_WriteBits( msg, trunc + FLOAT_INT_BIAS, FLOAT_INT_BITS );
                }
                else
                {
                    // send as full floating point value
                    MSG_WriteBits( msg, 1, 1 );
                    MSG_WriteBits( msg, *toF, 32 );
                }
            }
        }
        else
        {
            if (*toF == 0)
            {
                MSG_WriteBits( msg, 0, 1 );
            }
            else
            {
                MSG_WriteBits( msg, 1, 1 );
                // integer
                MSG_WriteBits( msg, *toF, field->bits );
            }
        }
    }
}

/*
==================
MSG_ReadDeltaEntity
 
The entity number has already been read from the message, which
is how the from state is identified.
 
If the delta removes the entity, entityState_t->number will be set to MAX_GENTITIES-1
 
Can go from either a baseline or a previous packet_entity
==================
*/
extern	cvar_t	*cl_shownet;

void MSG_ReadDeltaEntity( msg_t *msg, entityState_t *from, entityState_t *to,
                          int number)
{
    int			i, lc;
    int			numFields;
    netField_t	*field;
    int			*fromF, *toF;
    int			print;
    int			trunc;
    int			startBit, endBit;

    if ( number < 0 || number >= MAX_GENTITIES)
    {
        Com_Error( ERR_DROP, "Bad delta entity number: %i", number );
    }

    if ( msg->bit == 0 )
    {
        startBit = msg->readcount * 8 - GENTITYNUM_BITS;
    }
    else
    {
        startBit = ( msg->readcount - 1 ) * 8 + msg->bit - GENTITYNUM_BITS;
    }

    // check for a remove
    if ( MSG_ReadBits( msg, 1 ) == 1 )
    {
        Com_Memset( to, 0, sizeof( *to ) );
        to->number = MAX_GENTITIES - 1;
        if ( cl_shownet->integer >= 2 || cl_shownet->integer == -1 )
        {
            Com_Printf( "%3i: #%-3i remove\n", msg->readcount, number );
        }
        return;
    }

    // check for no delta
    if ( MSG_ReadBits( msg, 1 ) == 0 )
    {
        *to = *from;
        to->number = number;
        return;
    }

    numFields = sizeof(entityStateFields)/sizeof(entityStateFields[0]);
    lc = MSG_ReadByte(msg);

    // shownet 2/3 will interleave with other printed info, -1 will
    // just print the delta records`
    if ( cl_shownet->integer >= 2 || cl_shownet->integer == -1 )
    {
        print = 1;
        Com_Printf( "%3i: #%-3i ", msg->readcount, to->number );
    }
    else
    {
        print = 0;
    }

    to->number = number;

    for ( i = 0, field = entityStateFields ; i < lc ; i++, field++ )
    {
        fromF = (int *)( (byte *)from + field->offset );
        toF = (int *)( (byte *)to + field->offset );

        if ( ! MSG_ReadBits( msg, 1 ) )
        {
            // no change
            *toF = *fromF;
        }
        else
        {
            if ( field->bits == 0 )
            {
                // float
                if ( MSG_ReadBits( msg, 1 ) == 0 )
                {
                    *(float *)toF = 0.0f;
                }
                else
                {
                    if ( MSG_ReadBits( msg, 1 ) == 0 )
                    {
                        // integral float
                        trunc = MSG_ReadBits( msg, FLOAT_INT_BITS );
                        // bias to allow equal parts positive and negative
                        trunc -= FLOAT_INT_BIAS;
                        *(float *)toF = trunc;
                        if ( print )
                        {
                            Com_Printf( "%s:%i ", field->name, trunc );
                        }
                    }
                    else
                    {
                        // full floating point value
                        *toF = MSG_ReadBits( msg, 32 );
                        if ( print )
                        {
                            Com_Printf( "%s:%f ", field->name, *(float *)toF );
                        }
                    }
                }
            }
            else
            {
                if ( MSG_ReadBits( msg, 1 ) == 0 )
                {
                    *toF = 0;
                }
                else
                {
                    // integer
                    *toF = MSG_ReadBits( msg, field->bits );
                    if ( print )
                    {
                        Com_Printf( "%s:%i ", field->name, *toF );
                    }
                }
            }
            //			pcount[i]++;
        }
    }
    for ( i = lc, field = &entityStateFields[lc] ; i < numFields ; i++, field++ )
    {
        fromF = (int *)( (byte *)from + field->offset );
        toF = (int *)( (byte *)to + field->offset );
        // no change
        *toF = *fromF;
    }

    if ( print )
    {
        if ( msg->bit == 0 )
        {
            endBit = msg->readcount * 8 - GENTITYNUM_BITS;
        }
        else
        {
            endBit = ( msg->readcount - 1 ) * 8 + msg->bit - GENTITYNUM_BITS;
        }
        Com_Printf( " (%i bits)\n", endBit - startBit  );
    }
}


/*
============================================================================
 
plyer_state_t communication
 
============================================================================
*/

// using the stringizing operator to save typing...
#define	PSF(x) #x, offsetof(playerState_t, x)

netField_t	playerStateFields[] =
    {
        { PSF(commandTime), 32 },
        { PSF(origin[0]), 0 },
        { PSF(origin[1]), 0 },
        { PSF(bobCycle), 8 },
        { PSF(velocity[0]), 0 },
        { PSF(velocity[1]), 0 },
        { PSF(viewangles[1]), 0 },
        { PSF(viewangles[0]), 0 },
        { PSF(weaponTime), -16 },
        { PSF(origin[2]), 0 },
        { PSF(velocity[2]), 0 },
        { PSF(legsTimer), 8 },
        { PSF(pm_time), -16 },
        { PSF(eventSequence), 16 },
        { PSF(torsoAnim), 8 },
        { PSF(movementDir), 4 },
        { PSF(events[0]), 8 },
        { PSF(legsAnim), 8 },
        { PSF(events[1]), 8 },
        { PSF(pm_flags), 16 },
        { PSF(groundEntityNum), GENTITYNUM_BITS },
        { PSF(weaponState), 4 },
        { PSF(eFlags), 16 },
        { PSF(externalEvent), 10 },
        { PSF(gravity), 16 },
        { PSF(speed), 16 },
        { PSF(delta_angles[1]), 16 },
        { PSF(externalEventParm), 8 },
        { PSF(viewheight), -8 },
        { PSF(damageEvent), 8 },
        { PSF(damageYaw), 8 },
        { PSF(damagePitch), 8 },
        { PSF(damageCount), 8 },
        { PSF(generic1), 8 },
        { PSF(pm_type), 8 },
        { PSF(delta_angles[0]), 16 },
        { PSF(delta_angles[2]), 16 },
        { PSF(torsoTimer), 12 },
        { PSF(eventParms[0]), 8 },
        { PSF(eventParms[1]), 8 },
        { PSF(clientNum), 8 },
        { PSF(selectedWeapon), 5 },
        { PSF(viewangles[2]), 0 },
        { PSF(grapplePoint[0]), 0 },
        { PSF(grapplePoint[1]), 0 },
        { PSF(grapplePoint[2]), 0 },
        { PSF(jumppad_ent), 10 },
        { PSF(loopSound), 16 }
    };

/*
=============
MSG_WriteDeltaPlayerstate
 
=============
*/
void MSG_WriteDeltaPlayerstate( msg_t *msg, struct playerState_s *from, struct playerState_s *to )
{
    int				i;
    playerState_t	dummy;
    int				statsbits;
    int				persistantbits;
    int				ammobits;
    int				powerupbits;
    int				numFields;
    int				c;
    netField_t		*field;
    int				*fromF, *toF;
    float			fullFloat;
    int				trunc, lc;

    if (!from)
    {
        from = &dummy;
        Com_Memset (&dummy, 0, sizeof(dummy));
    }

    c = msg->cursize;

    numFields = sizeof( playerStateFields ) / sizeof( playerStateFields[0] );

    lc = 0;
    for ( i = 0, field = playerStateFields ; i < numFields ; i++, field++ )
    {
        fromF = (int *)( (byte *)from + field->offset );
        toF = (int *)( (byte *)to + field->offset );
        if ( *fromF != *toF )
        {
            lc = i+1;
        }
    }

    MSG_WriteByte( msg, lc );	// # of changes

    oldsize += numFields - lc;

    for ( i = 0, field = playerStateFields ; i < lc ; i++, field++ )
    {
        fromF = (int *)( (byte *)from + field->offset );
        toF = (int *)( (byte *)to + field->offset );

        if ( *fromF == *toF )
        {
            MSG_WriteBits( msg, 0, 1 );	// no change
            continue;
        }

        MSG_WriteBits( msg, 1, 1 );	// changed
        //		pcount[i]++;

        if ( field->bits == 0 )
        {
            // float
            fullFloat = *(float *)toF;
            trunc = (int)fullFloat;

            if ( trunc == fullFloat && trunc + FLOAT_INT_BIAS >= 0 &&
                    trunc + FLOAT_INT_BIAS < ( 1 << FLOAT_INT_BITS ) )
            {
                // send as small integer
                MSG_WriteBits( msg, 0, 1 );
                MSG_WriteBits( msg, trunc + FLOAT_INT_BIAS, FLOAT_INT_BITS );
            }
            else
            {
                // send as full floating point value
                MSG_WriteBits( msg, 1, 1 );
                MSG_WriteBits( msg, *toF, 32 );
            }
        }
        else
        {
            // integer
            MSG_WriteBits( msg, *toF, field->bits );
        }
    }
    c = msg->cursize - c;


    //
    // send the arrays
    //
    statsbits = 0;
    for (i=0 ; i<16 ; i++)
    {
        if (to->stats[i] != from->stats[i])
        {
            statsbits |= 1<<i;
        }
    }
    persistantbits = 0;
    for (i=0 ; i<16 ; i++)
    {
        if (to->persistant[i] != from->persistant[i])
        {
            persistantbits |= 1<<i;
        }
    }
    ammobits = 0;
    for (i=0 ; i<3 ; i++)
    {
        if (to->weaponAmmo[i] != from->weaponAmmo[i])
        {
            ammobits |= 1<<i;
        }
    }
    powerupbits = 0;
    for (i=0 ; i<16 ; i++)
    {
        if (to->powerups[i] != from->powerups[i])
        {
            powerupbits |= 1<<i;
        }
    }

    if (!statsbits && !persistantbits && !ammobits && !powerupbits)
    {
        MSG_WriteBits( msg, 0, 1 );	// no change
        oldsize += 4;
        return;
    }
    MSG_WriteBits( msg, 1, 1 );	// changed

    if ( statsbits )
    {
        MSG_WriteBits( msg, 1, 1 );	// changed
        MSG_WriteShort( msg, statsbits );
        for (i=0 ; i<16 ; i++)
            if (statsbits & (1<<i) )
                MSG_WriteShort (msg, to->stats[i]);
    }
    else
    {
        MSG_WriteBits( msg, 0, 1 );	// no change
    }


    if ( persistantbits )
    {
        MSG_WriteBits( msg, 1, 1 );	// changed
        MSG_WriteShort( msg, persistantbits );
        for (i=0 ; i<16 ; i++)
            if (persistantbits & (1<<i) )
                MSG_WriteShort (msg, to->persistant[i]);
    }
    else
    {
        MSG_WriteBits( msg, 0, 1 );	// no change
    }


    if ( ammobits )
    {
        MSG_WriteBits( msg, 1, 1 );	// changed
        MSG_WriteShort( msg, ammobits );
        for (i=0 ; i<3 ; i++)
            if (ammobits & (1<<i) )
                MSG_WriteShort(msg, (int)(to->weaponAmmo[i]));
    }
    else
    {
        MSG_WriteBits( msg, 0, 1 );	// no change
    }


    if ( powerupbits )
    {
        MSG_WriteBits( msg, 1, 1 );	// changed
        MSG_WriteShort( msg, powerupbits );
        for (i=0 ; i<16 ; i++)
            if (powerupbits & (1<<i) )
                MSG_WriteLong( msg, to->powerups[i] );
    }
    else
    {
        MSG_WriteBits( msg, 0, 1 );	// no change
    }
}


/*
===================
MSG_ReadDeltaPlayerstate
===================
*/
void MSG_ReadDeltaPlayerstate (msg_t *msg, playerState_t *from, playerState_t *to )
{
    int			i, lc;
    int			bits;
    netField_t	*field;
    int			numFields;
    int			startBit, endBit;
    int			print;
    int			*fromF, *toF;
    int			trunc;
    playerState_t	dummy;

    if ( !from )
    {
        from = &dummy;
        Com_Memset( &dummy, 0, sizeof( dummy ) );
    }
    *to = *from;

    if ( msg->bit == 0 )
    {
        startBit = msg->readcount * 8 - GENTITYNUM_BITS;
    }
    else
    {
        startBit = ( msg->readcount - 1 ) * 8 + msg->bit - GENTITYNUM_BITS;
    }

    // shownet 2/3 will interleave with other printed info, -2 will
    // just print the delta records
    if ( cl_shownet->integer >= 2 || cl_shownet->integer == -2 )
    {
        print = 1;
        Com_Printf( "%3i: playerstate ", msg->readcount );
    }
    else
    {
        print = 0;
    }

    numFields = sizeof( playerStateFields ) / sizeof( playerStateFields[0] );
    lc = MSG_ReadByte(msg);

    for ( i = 0, field = playerStateFields ; i < lc ; i++, field++ )
    {
        fromF = (int *)( (byte *)from + field->offset );
        toF = (int *)( (byte *)to + field->offset );

        if ( ! MSG_ReadBits( msg, 1 ) )
        {
            // no change
            *toF = *fromF;
        }
        else
        {
            if ( field->bits == 0 )
            {
                // float
                if ( MSG_ReadBits( msg, 1 ) == 0 )
                {
                    // integral float
                    trunc = MSG_ReadBits( msg, FLOAT_INT_BITS );
                    // bias to allow equal parts positive and negative
                    trunc -= FLOAT_INT_BIAS;
                    *(float *)toF = trunc;
                    if ( print )
                    {
                        Com_Printf( "%s:%i ", field->name, trunc );
                    }
                }
                else
                {
                    // full floating point value
                    *toF = MSG_ReadBits( msg, 32 );
                    if ( print )
                    {
                        Com_Printf( "%s:%f ", field->name, *(float *)toF );
                    }
                }
            }
            else
            {
                // integer
                *toF = MSG_ReadBits( msg, field->bits );
                if ( print )
                {
                    Com_Printf( "%s:%i ", field->name, *toF );
                }
            }
        }
    }
    for ( i=lc,field = &playerStateFields[lc];i<numFields; i++, field++)
    {
        fromF = (int *)( (byte *)from + field->offset );
        toF = (int *)( (byte *)to + field->offset );
        // no change
        *toF = *fromF;
    }


    // read the arrays
    if (MSG_ReadBits( msg, 1 ) )
    {
        // parse stats
        if ( MSG_ReadBits( msg, 1 ) )
        {
            LOG("PS_STATS");
            bits = MSG_ReadShort (msg);
            for (i=0 ; i<16 ; i++)
            {
                if (bits & (1<<i) )
                {
                    to->stats[i] = MSG_ReadShort(msg);
                }
            }
        }

        // parse persistant stats
        if ( MSG_ReadBits( msg, 1 ) )
        {
            LOG("PS_PERSISTANT");
            bits = MSG_ReadShort (msg);
            for (i=0 ; i<16 ; i++)
            {
                if (bits & (1<<i) )
                {
                    to->persistant[i] = MSG_ReadShort(msg);
                }
            }
        }

        // parse ammo
        if ( MSG_ReadBits( msg, 1 ) )
        {
            LOG("PS_AMMO");
            bits = MSG_ReadShort (msg);
            for (i=0 ; i<3 ; i++)
            {
                if (bits & (1<<i) )
                {
                    to->weaponAmmo[i] = MSG_ReadShort(msg);
                }
            }
        }

        // parse powerups
        if ( MSG_ReadBits( msg, 1 ) )
        {
            LOG("PS_POWERUPS");
            bits = MSG_ReadShort (msg);
            for (i=0 ; i<16 ; i++)
            {
                if (bits & (1<<i) )
                {
                    to->powerups[i] = MSG_ReadLong(msg);
                }
            }
        }
    }

    if ( print )
    {
        if ( msg->bit == 0 )
        {
            endBit = msg->readcount * 8 - GENTITYNUM_BITS;
        }
        else
        {
            endBit = ( msg->readcount - 1 ) * 8 + msg->bit - GENTITYNUM_BITS;
        }
        Com_Printf( " (%i bits)\n", endBit - startBit  );
    }
}

int msg_hData[256] = {
                         250315,			// 0
                         41193,			// 1
                         6292,			// 2
                         7106,			// 3
                         3730,			// 4
                         3750,			// 5
                         6110,			// 6
                         23283,			// 7
                         33317,			// 8
                         6950,			// 9
                         7838,			// 10
                         9714,			// 11
                         9257,			// 12
                         17259,			// 13
                         3949,			// 14
                         1778,			// 15
                         8288,			// 16
                         1604,			// 17
                         1590,			// 18
                         1663,			// 19
                         1100,			// 20
                         1213,			// 21
                         1238,			// 22
                         1134,			// 23
                         1749,			// 24
                         1059,			// 25
                         1246,			// 26
                         1149,			// 27
                         1273,			// 28
                         4486,			// 29
                         2805,			// 30
                         3472,			// 31
                         21819,			// 32
                         1159,			// 33
                         1670,			// 34
                         1066,			// 35
                         1043,			// 36
                         1012,			// 37
                         1053,			// 38
                         1070,			// 39
                         1726,			// 40
                         888,			// 41
                         1180,			// 42
                         850,			// 43
                         960,			// 44
                         780,			// 45
                         1752,			// 46
                         3296,			// 47
                         10630,			// 48
                         4514,			// 49
                         5881,			// 50
                         2685,			// 51
                         4650,			// 52
                         3837,			// 53
                         2093,			// 54
                         1867,			// 55
                         2584,			// 56
                         1949,			// 57
                         1972,			// 58
                         940,			// 59
                         1134,			// 60
                         1788,			// 61
                         1670,			// 62
                         1206,			// 63
                         5719,			// 64
                         6128,			// 65
                         7222,			// 66
                         6654,			// 67
                         3710,			// 68
                         3795,			// 69
                         1492,			// 70
                         1524,			// 71
                         2215,			// 72
                         1140,			// 73
                         1355,			// 74
                         971,			// 75
                         2180,			// 76
                         1248,			// 77
                         1328,			// 78
                         1195,			// 79
                         1770,			// 80
                         1078,			// 81
                         1264,			// 82
                         1266,			// 83
                         1168,			// 84
                         965,			// 85
                         1155,			// 86
                         1186,			// 87
                         1347,			// 88
                         1228,			// 89
                         1529,			// 90
                         1600,			// 91
                         2617,			// 92
                         2048,			// 93
                         2546,			// 94
                         3275,			// 95
                         2410,			// 96
                         3585,			// 97
                         2504,			// 98
                         2800,			// 99
                         2675,			// 100
                         6146,			// 101
                         3663,			// 102
                         2840,			// 103
                         14253,			// 104
                         3164,			// 105
                         2221,			// 106
                         1687,			// 107
                         3208,			// 108
                         2739,			// 109
                         3512,			// 110
                         4796,			// 111
                         4091,			// 112
                         3515,			// 113
                         5288,			// 114
                         4016,			// 115
                         7937,			// 116
                         6031,			// 117
                         5360,			// 118
                         3924,			// 119
                         4892,			// 120
                         3743,			// 121
                         4566,			// 122
                         4807,			// 123
                         5852,			// 124
                         6400,			// 125
                         6225,			// 126
                         8291,			// 127
                         23243,			// 128
                         7838,			// 129
                         7073,			// 130
                         8935,			// 131
                         5437,			// 132
                         4483,			// 133
                         3641,			// 134
                         5256,			// 135
                         5312,			// 136
                         5328,			// 137
                         5370,			// 138
                         3492,			// 139
                         2458,			// 140
                         1694,			// 141
                         1821,			// 142
                         2121,			// 143
                         1916,			// 144
                         1149,			// 145
                         1516,			// 146
                         1367,			// 147
                         1236,			// 148
                         1029,			// 149
                         1258,			// 150
                         1104,			// 151
                         1245,			// 152
                         1006,			// 153
                         1149,			// 154
                         1025,			// 155
                         1241,			// 156
                         952,			// 157
                         1287,			// 158
                         997,			// 159
                         1713,			// 160
                         1009,			// 161
                         1187,			// 162
                         879,			// 163
                         1099,			// 164
                         929,			// 165
                         1078,			// 166
                         951,			// 167
                         1656,			// 168
                         930,			// 169
                         1153,			// 170
                         1030,			// 171
                         1262,			// 172
                         1062,			// 173
                         1214,			// 174
                         1060,			// 175
                         1621,			// 176
                         930,			// 177
                         1106,			// 178
                         912,			// 179
                         1034,			// 180
                         892,			// 181
                         1158,			// 182
                         990,			// 183
                         1175,			// 184
                         850,			// 185
                         1121,			// 186
                         903,			// 187
                         1087,			// 188
                         920,			// 189
                         1144,			// 190
                         1056,			// 191
                         3462,			// 192
                         2240,			// 193
                         4397,			// 194
                         12136,			// 195
                         7758,			// 196
                         1345,			// 197
                         1307,			// 198
                         3278,			// 199
                         1950,			// 200
                         886,			// 201
                         1023,			// 202
                         1112,			// 203
                         1077,			// 204
                         1042,			// 205
                         1061,			// 206
                         1071,			// 207
                         1484,			// 208
                         1001,			// 209
                         1096,			// 210
                         915,			// 211
                         1052,			// 212
                         995,			// 213
                         1070,			// 214
                         876,			// 215
                         1111,			// 216
                         851,			// 217
                         1059,			// 218
                         805,			// 219
                         1112,			// 220
                         923,			// 221
                         1103,			// 222
                         817,			// 223
                         1899,			// 224
                         1872,			// 225
                         976,			// 226
                         841,			// 227
                         1127,			// 228
                         956,			// 229
                         1159,			// 230
                         950,			// 231
                         7791,			// 232
                         954,			// 233
                         1289,			// 234
                         933,			// 235
                         1127,			// 236
                         3207,			// 237
                         1020,			// 238
                         927,			// 239
                         1355,			// 240
                         768,			// 241
                         1040,			// 242
                         745,			// 243
                         952,			// 244
                         805,			// 245
                         1073,			// 246
                         740,			// 247
                         1013,			// 248
                         805,			// 249
                         1008,			// 250
                         796,			// 251
                         996,			// 252
                         1057,			// 253
                         11457,			// 254
                         13504,			// 255
                     };

void MSG_initHuffman(void)
{
    int i,j;

    msgInit = qtrue;
    Huff_Init(&msgHuff);
    for(i=0;i<256;i++)
    {
        for (j=0;j<msg_hData[i];j++)
        {
            Huff_addRef(&msgHuff.compressor,	(byte)i);			// Do update
            Huff_addRef(&msgHuff.decompressor,	(byte)i);			// Do update
        }
    }
}

/*
void MSG_NUinitHuffman() {
	byte	*data;
	int		size, i, ch;
	int		array[256];
 
	msgInit = qtrue;
 
	Huff_Init(&msgHuff);
	// load it in
	size = FS_ReadFile( "netchan/netchan.bin", (void **)&data );
 
	for(i=0;i<256;i++) {
		array[i] = 0;
	}
	for(i=0;i<size;i++) {
		ch = data[i];
		Huff_addRef(&msgHuff.compressor,	ch);			// Do update
		Huff_addRef(&msgHuff.decompressor,	ch);			// Do update
		array[ch]++;
	}
	Com_Printf("msg_hData {\n");
	for(i=0;i<256;i++) {
		if (array[i] == 0) {
			Huff_addRef(&msgHuff.compressor,	i);			// Do update
			Huff_addRef(&msgHuff.decompressor,	i);			// Do update
		}
		Com_Printf("%d,			// %d\n", array[i], i);
	}
	Com_Printf("};\n");
	FS_FreeFile( data );
	Cbuf_AddText( "condump dump.txt\n" );
}
*/

//===========================================================================
